from itertools import combinations

import numpy as np
import pandas as pd

# pearson相关系数=样本协方差/两特征的标准差之积
# 样本协方差 Cov(x,y) = Sum{ [(Xi - X_mean)* (Yi - Y_mean)] / (n-1)}

pd_data = pd.DataFrame(
    [[1, 33, 4], [4, 4, 6], [12, 7, 99], [34, 54, 22], [23, 56, 2]],
    columns=['x_0', 'x_1', 'x_2'])
print(pd_data)
pd_corr = pd_data.corr('pearson')
print(pd_corr)


def cov_x_y(x: pd.Series, y: pd.Series):
    mean_x = x.mean()
    mean_y = y.mean()
    return ((x - mean_x) * (y - mean_y)).sum() / (x.shape[0] - 1)


x_std_1 = pd_data['x_0'].std()
x_std_2 = np.sqrt(cov_x_y(pd_data['x_0'], pd_data['x_0']))
print(x_std_1, x_std_2)


def pearson(data_frame: pd.DataFrame):
    data_headers = data_frame.columns.values

    data_headers_mapper = {i: idx for idx, i in enumerate(data_headers)}

    K = len(data_headers)
    correl = np.empty((K, K), dtype=float)

    for i in range(len(correl)):
        correl[i][i] = 1

    for h1, h2 in combinations(data_headers, 2):
        cov = cov_x_y(data_frame[h1], data_frame[h2])
        rs_val = cov / (data_frame[h1].std() * data_frame[h2].std())
        correl[data_headers_mapper[h1]][data_headers_mapper[h2]] = rs_val
        correl[data_headers_mapper[h2]][data_headers_mapper[h1]] = rs_val

    return pd.DataFrame(correl, index=data_headers, columns=data_headers)


print(pearson(pd_data))
